ipv6编程

您所在的位置:网站首页 java ping ipv6编程

ipv6编程

2023-09-18 04:44| 来源: 网络整理| 查看: 265

1. Java支持IPv6 在 IPv6 的环境下开发 Java 应用,或者移植已有的 IPv4 环境下开发的Java 应用到 IPv6 环境中来,对于 IPv6 网络地址的验证是必须的步骤,尤其是提供了 UI(用户接口)的 Java 应用。

2. 获取本机IPv6地址

有时为了能够注册 listener,需要使用本机的 IPv6 地址,这一地址不能简单得通过 InetAddress.getLocalhost() 获得。因为这样有可能获得诸如 0:0:0:0:0:0:0:1 这样的特殊地址。使用这样的地址,其他服务器将无法把通知发送到本机上,因此必须先进行过滤,选出确实可用的地址。以下代码实现了这一功能,思路是遍历网络接口的各个地址,直至找到符合要求的地址。

package com.text; import java.io.IOException; import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.util.Enumeration; public class Get_IPv6 { public static void main(String[] args) throws IOException{ String str = getLocalIPv6Address(); System.out.println(str); } public static String getLocalIPv6Address() throws IOException { InetAddress inetAddress = null; Enumeration networkInterfaces = NetworkInterface .getNetworkInterfaces(); outer: while (networkInterfaces.hasMoreElements()) { Enumeration inetAds = networkInterfaces.nextElement() .getInetAddresses(); while (inetAds.hasMoreElements()) { inetAddress = inetAds.nextElement(); //Check if it's ipv6 address and reserved address if (inetAddress instanceof Inet6Address && !isReservedAddr(inetAddress)) { break outer; } } } String ipAddr = inetAddress.getHostAddress(); // Filter network card No int index = ipAddr.indexOf('%'); if (index > 0) { ipAddr = ipAddr.substring(0, index); } return ipAddr; } private static boolean isReservedAddr(InetAddress inetAddr) { if (inetAddr.isAnyLocalAddress() || inetAddr.isLinkLocalAddress() || inetAddr.isLoopbackAddress()) { return true; } return false; } }

为了支持 IPv6,Java 中增加了两个 InetAddress 的子类:Inet4Address和 Inet6Address。一般情况下这两个子类并不会被使用到,但是当我们需要分别处理不同的 IP 协议时就非常有用,在这我们根据Inet6Address来筛选地址。  isReservedAddr() 方法过滤了本机特殊 IP 地址,包括“LocalAddress”,“LinkLocalAddress”和“LoopbackAddress”。

注:在 windows 平台上,取得的 IPv6 地址后面可能跟了一个百分号加数字。这里的数字是本机网络适配器的编号。这个后缀并不是 IPv6 标准地址的一部分,可以去除。

3. IPv4/IPv6 双环境下,网络的选择和测试

Java 提供了 InetAddress 的两个扩展类以供使用:Inet4Address 和 Inet6Address,其中封装了对于 IPv4 和 IPv6 的特殊属性和行为。然而由于Java 的多态特性,使得程序员一般只需要使用父类 InetAddress,Java 虚拟机可以根据所封装的 IP 地址类型的不同,在运行时选择正确的行为逻辑。  在 IPv4/IPv6 双环境中,对于使用 Java 开发的网络应用,比较值得注意的是以下两个 IPv6 相关的 Java 虚拟机系统属性。  java.net.preferIPv4Stack=  java.net.preferIPv6Addresses=  程序中设置代码如下:  System.setProperty("java.net.preferIPv6Addresses","true");  preferIPv4Stack(默认 false)表示如果存在 IPv4 和 IPv6 双栈,Java 程序是否优先使用 IPv4 套接字。默认值是优先使用 IPv6 套接字,因为 IPv6 套接字可以与对应的 IPv4 或 IPv6 主机进行对话;相反如果优先使用 IPv4,则只不能与 IPv6 主机进行通信。  preferIPv6Addresses(默认 false)表示在查询本地或远端 IP 地址时,如果存在 IPv4 和 IPv6 双地址,Java 程序是否优先返回 IPv6 地址。Java 默认返回 IPv4 地址主要是为了向后兼容,以支持旧有的 IPv4 验证逻辑,以及旧有的仅支持 IPv4 地址的服务。

4. socket 支持 IPv6 通信示例

客户端:

package com.text2; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.Socket; import java.util.Enumeration; public class Click { public static void main(String[] args) throws IOException { //获取本机IPv6地址getLocalIPv6Address()方法在上面已经提到 String servernameString = getLocalIPv6Address(); System.out.println("客户端启动…"); System.out.println("当接收到服务器端字符为 \"OK\" 的时候, 客户端将终止\n"); while (true) { Socket socket = null; try { // 创建一个流套接字并将其连接到指定主机上的指定端口号 socket = new Socket(servernameString, 8080); // 读取服务器端数据 DataInputStream input = new DataInputStream(socket.getInputStream()); // 向服务器端发送数据 DataOutputStream out = new DataOutputStream(socket.getOutputStream()); System.out.print("请输入: \t"); String str = new BufferedReader(new InputStreamReader(System.in)).readLine(); out.writeUTF(str); String ret = input.readUTF(); System.out.println("服务器端返回过来的是: " + ret); if ("OK".equals(ret)) { System.out.println("客户端将关闭连接"); Thread.sleep(500); break; } out.close(); input.close(); } catch (Exception e) { System.out.println("客户端异常:" + e.getMessage()); } finally { if (socket != null) { try { socket.close(); } catch (IOException e) { socket = null; System.out.println("客户端 finally 异常:" + e.getMessage()); } } } } } public static String getLocalIPv6Address() throws IOException { InetAddress inetAddress = null; Enumeration networkInterfaces = NetworkInterface .getNetworkInterfaces(); outer: while (networkInterfaces.hasMoreElements()) { Enumeration inetAds = networkInterfaces.nextElement() .getInetAddresses(); while (inetAds.hasMoreElements()) { inetAddress = inetAds.nextElement(); //Check if it's ipv6 address and reserved address if (inetAddress instanceof Inet6Address && !isReservedAddr(inetAddress)) { break outer; } } } String ipAddr = inetAddress.getHostAddress(); // Filter network card No int index = ipAddr.indexOf('%'); if (index > 0) { ipAddr = ipAddr.substring(0, index); } return ipAddr; } private static boolean isReservedAddr(InetAddress inetAddr) { if (inetAddr.isAnyLocalAddress() || inetAddr.isLinkLocalAddress()|| inetAddr.isLoopbackAddress()) { return true; } return false; } }

服务器端:

package com.text2; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("服务器启动…\n"); Server server = new Server(); server.init(); } public void init() { try { ServerSocket serverSocket = new ServerSocket(8080); while (true) { // 一旦有堵塞, 则表示服务器与客户端获得了连接 Socket client = serverSocket.accept(); // 处理这次连接 new HandlerThread(client); } } catch (Exception e) { System.out.println("服务器异常: " + e.getMessage()); } } private class HandlerThread implements Runnable { private Socket socket; public HandlerThread(Socket client) { socket = client; new Thread(this).start(); } public void run() { try { // 读取客户端数据 DataInputStream input = new DataInputStream(socket.getInputStream()); String clientInputStr = input.readUTF(); //这里要注意和客户端输出流的写方法对应,否则会抛 EOFException // 处理客户端数据 System.out.println("客户端发过来的内容:" + clientInputStr); // 向客户端回复信息 DataOutputStream out = new DataOutputStream(socket.getOutputStream()); System.out.print("请输入:\t"); // 发送键盘输入的一行 String s = new BufferedReader(new InputStreamReader(System.in)).readLine(); out.writeUTF(s); out.close(); input.close(); } catch (Exception e) { System.out.println("服务器 run 异常: " + e.getMessage()); } finally { if (socket != null) { try { socket.close(); } catch (Exception e) { socket = null; System.out.println("服务端 finally 异常:" + e.getMessage()); } } } } } }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3